home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 726-750 / 741 / rkrm_lib1 / rkrm_lib1.lha / Intuition / Menus / menulayout.c < prev    next >
C/C++ Source or Header  |  1992-09-03  |  22KB  |  581 lines

  1. ;/* menulayout.c - Execute me to compile me with SAS C 5.10
  2. LC -b1 -cfistq -v -y -j73 menulayout.c
  3. Blink FROM LIB:c.o,menulayout.o TO menulayout LIBRARY LIB:LC.lib,LIB:Amiga.lib
  4. quit
  5. */
  6.  
  7. /*
  8. Copyright (c) 1992 Commodore-Amiga, Inc.
  9.  
  10. This example is provided in electronic form by Commodore-Amiga, Inc. for
  11. use with the "Amiga ROM Kernel Reference Manual: Libraries", 3rd Edition,
  12. published by Addison-Wesley (ISBN 0-201-56774-1).
  13.  
  14. The "Amiga ROM Kernel Reference Manual: Libraries" contains additional
  15. information on the correct usage of the techniques and operating system
  16. functions presented in these examples.  The source and executable code
  17. of these examples may only be distributed in free electronic form, via
  18. bulletin board or as part of a fully non-commercial and freely
  19. redistributable diskette.  Both the source and executable code (including
  20. comments) must be included, without modification, in any copy.  This
  21. example may not be published in printed form or distributed with any
  22. commercial product.  However, the programming techniques and support
  23. routines set forth in these examples may be used in the development
  24. of original executable software products for Commodore Amiga computers.
  25.  
  26. All other rights reserved.
  27.  
  28. This example is provided "as-is" and is subject to change; no
  29. warranties are made.  All use is at your own risk. No liability or
  30. responsibility is assumed.
  31. */
  32.  
  33. /*
  34. ** menulayout.c - Example showing how to do menu layout in general.  This example
  35. ** also illustrates handling menu events, including IDCMP_MENUHELP events.
  36. **
  37. ** Note that handling arbitrary fonts is fairly complex.  Applications that require V37
  38. ** should use the simpler menu layout routines found in the GadTools library.
  39. */
  40. #define INTUI_V36_NAMES_ONLY
  41.  
  42. #include <exec/types.h>
  43. #include <intuition/intuition.h>
  44. #include <intuition/intuitionbase.h>
  45. #include <graphics/gfxbase.h>
  46. #include <dos/dos.h>
  47. #include <clib/exec_protos.h>
  48. #include <clib/graphics_protos.h>
  49. #include <clib/intuition_protos.h>
  50. #include <stdlib.h>
  51. #include <stdio.h>
  52. #include <string.h>
  53.  
  54. #ifdef LATTICE
  55. int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
  56. int chkabort(void) { return(0); }  /* really */
  57. #endif
  58. /* Our function prototypes */
  59. BOOL processMenus(USHORT selection, BOOL done);
  60. BOOL handleIDCMP(struct Window *win);
  61. USHORT MaxLength(struct RastPort *textRPort, struct MenuItem *first_item, USHORT char_size);
  62. VOID setITextAttr(struct IntuiText *first_IText, struct TextAttr *textAttr);
  63. VOID adjustItems(struct RastPort *textRPort, struct MenuItem *first_item, struct TextAttr *textAttr,
  64.                  USHORT char_size, USHORT height, USHORT level, USHORT left_edge);
  65. BOOL adjustMenus(struct Menu *first_menu, struct TextAttr *textAttr);
  66. LONG doWindow(void);
  67.  
  68. /* Settings Item IntuiText */
  69. struct IntuiText SettText[] = {
  70.         {0,1,JAM2,2,         1, NULL, "Sound...",        NULL },
  71.         {0,1,JAM2,CHECKWIDTH,1, NULL, " Auto Save",      NULL },
  72.         {0,1,JAM2,CHECKWIDTH,1, NULL, " Have Your Cake", NULL },
  73.         {0,1,JAM2,CHECKWIDTH,1, NULL, " Eat It Too",     NULL }
  74.     };
  75.  
  76. struct MenuItem SettItem[] = {
  77.         { /* "Sound..." */
  78.             &SettItem[1], 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0,
  79.             (APTR)&SettText[0], NULL, NULL, NULL, MENUNULL },
  80.         { /* "Auto Save" (toggle-select, initially selected) */
  81.             &SettItem[2], 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP|CHECKIT|MENUTOGGLE|CHECKED, 0,
  82.             (APTR)&SettText[1], NULL, NULL, NULL, MENUNULL },
  83.         { /* "Have Your Cake" (initially selected, excludes "Eat It Too") */
  84.             &SettItem[3], 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP|CHECKIT|CHECKED, 8,
  85.             (APTR)&SettText[2], NULL, NULL, NULL, MENUNULL },
  86.         { /* "Eat It Too" (excludes "Have Your Cake") */
  87.             NULL, 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP|CHECKIT, 4,
  88.             (APTR)&SettText[3], NULL, NULL, NULL, MENUNULL }
  89.     };
  90.  
  91. /* Edit Menu Item IntuiText */
  92. struct IntuiText EditText[] = {
  93.         {0,1,JAM2,2,1, NULL, "Cut",       NULL },
  94.         {0,1,JAM2,2,1, NULL, "Copy",      NULL },
  95.         {0,1,JAM2,2,1, NULL, "Paste",     NULL },
  96.         {0,1,JAM2,2,1, NULL, "Erase",     NULL },
  97.         {0,1,JAM2,2,1, NULL, "Undo",      NULL }
  98.     };
  99.  
  100. /* Edit Menu Items */
  101. struct MenuItem EditItem[] = {
  102.         { /* "Cut" (key-equivalent: 'X') */
  103.             &EditItem[1], 0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  104.             (APTR)&EditText[0], NULL, 'X', NULL, MENUNULL },
  105.         { /* "Copy" (key-equivalent: 'C') */
  106.             &EditItem[2], 0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  107.             (APTR)&EditText[1], NULL, 'C', NULL, MENUNULL },
  108.         { /* "Paste" (key-equivalent: 'V') */
  109.             &EditItem[3], 0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  110.             (APTR)&EditText[2], NULL, 'V', NULL, MENUNULL },
  111.         { /* "Erase" (disabled) */
  112.             &EditItem[4], 0, 0, 0, 0, ITEMTEXT|HIGHCOMP, 0,
  113.             (APTR)&EditText[3], NULL, NULL, NULL, MENUNULL },
  114.         { /* "Undo" MenuItem (key-equivalent: 'Z') */
  115.             NULL, 0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  116.             (APTR)&EditText[4], NULL, 'Z', NULL, MENUNULL }
  117.     };
  118.  
  119. /* IntuiText for the Print Sub-Items */
  120. struct IntuiText PrtText[] = {
  121.         {0,1, JAM2,2,1, NULL, "NLQ",   NULL },
  122.         {0,1, JAM2,2,1, NULL, "Draft", NULL }
  123.     };
  124.  
  125. /* Print Sub-Items */
  126. struct MenuItem PrtItem[] = {
  127.         { /* "NLQ" */
  128.             &PrtItem[1], 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0,
  129.             (APTR)&PrtText[0], NULL, NULL, NULL, MENUNULL },
  130.         { /* "Draft" */
  131.             NULL, 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0,
  132.             (APTR)&PrtText[1], NULL, NULL, NULL, MENUNULL }
  133.     };
  134. /* Uses the >> character to indicate a sub-menu item.
  135. ** This is \273 Octal, 0xBB Hex or Alt-0 from the Keyboard.
  136. **
  137. ** NOTE that standard menus place this character at the right margin of the menu box.
  138. ** This may be done by using a second IntuiText structure for the single character,
  139. ** linking this IntuiText to the first one, and positioning the IntuiText so that the
  140. ** character appears at the right margin.  GadTools library will provide the correct behavior.
  141. */
  142.  
  143. /* Project Menu Item IntuiText */
  144. struct IntuiText ProjText[] = {
  145.         {0,1, JAM2,2,1, NULL, "New",         NULL },
  146.         {0,1, JAM2,2,1, NULL, "Open...",     NULL },
  147.         {0,1, JAM2,2,1, NULL, "Save",        NULL },
  148.         {0,1, JAM2,2,1, NULL, "Save As...",  NULL },
  149.         {0,1, JAM2,2,1, NULL, "Print     \273", NULL },
  150.         {0,1, JAM2,2,1, NULL, "About...",    NULL },
  151.         {0,1, JAM2,2,1, NULL, "Quit",        NULL }
  152.     };
  153.  
  154.  
  155. /* Project Menu Items */
  156. struct MenuItem ProjItem[] = {
  157.         { /* "New" (key-equivalent: 'N' */
  158.             &ProjItem[1],0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  159.             (APTR)&ProjText[0], NULL, 'N', NULL, MENUNULL },
  160.         { /* "Open..." (key-equivalent: 'O') */
  161.             &ProjItem[2],0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  162.             (APTR)&ProjText[1], NULL, 'O', NULL, MENUNULL },
  163.         { /* "Save" (key-equivalent: 'S') */
  164.             &ProjItem[3],0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  165.             (APTR)&ProjText[2], NULL, 'S', NULL, MENUNULL },
  166.         { /* "Save As..." (key-equivalent: 'A') */
  167.             &ProjItem[4],0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  168.             (APTR)&ProjText[3], NULL, 'A', NULL, MENUNULL },
  169.         { /* "Print" (has sub-menu) */
  170.             &ProjItem[5],0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0,
  171.             (APTR)&ProjText[4], NULL, NULL, &PrtItem[0], MENUNULL },
  172.         { /* "About..." */
  173.             &ProjItem[6],0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0,
  174.             (APTR)&ProjText[5], NULL, NULL, NULL, MENUNULL },
  175.         { /* "Quit" (key-equivalent: 'Q' */
  176.             NULL, 0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  177.             (APTR)&ProjText[6], NULL, 'Q', NULL, MENUNULL }
  178.     };
  179.  
  180. /* Menu Titles */
  181. struct Menu Menus[] = {
  182.         {&Menus[1],  0, 0, 63, 0, MENUENABLED, "Project",    &ProjItem[0]},
  183.         {&Menus[2], 70, 0, 39, 0, MENUENABLED, "Edit",       &EditItem[0]},
  184.         {NULL,     120, 0, 88, 0, MENUENABLED, "Settings",   &SettItem[0]},
  185.     };
  186.  
  187. /* A pointer to the first menu for easy reference */
  188. struct Menu *FirstMenu = &Menus[0];
  189.  
  190. /* Window Text for Explanation of Program */
  191. struct IntuiText WinText[] = {
  192.         {0, 0, JAM2, 0, 0, NULL, "How to do a Menu", NULL},
  193.         {0, 0, JAM2, 0, 0, NULL, "(with Style)", &WinText[0]}
  194.     };
  195.  
  196. /* Globals */
  197. struct Library  *IntuitionBase = NULL;
  198. struct Library  *GfxBase = NULL;
  199.  
  200. /* open all of the required libraries.  Note that we require
  201. ** Intuition V37, as the routine uses OpenWindowTags().
  202. */
  203. VOID main(int argc, char **argv)
  204. {
  205. LONG returnValue;
  206.  
  207. /* This gets set to RETURN_OK if everything goes well. */
  208. returnValue = RETURN_FAIL;
  209.  
  210. /* Open the Intuition Library */
  211. IntuitionBase = OpenLibrary("intuition.library", 37);
  212. if (IntuitionBase)
  213.     {
  214.     /* Open the Graphics Library */
  215.     GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 33);
  216.     if (GfxBase)
  217.         {
  218.         returnValue = doWindow();
  219.  
  220.         CloseLibrary(GfxBase);
  221.         }
  222.     CloseLibrary(IntuitionBase);
  223.     }
  224. exit(returnValue);
  225. }
  226.  
  227. /* Open a window with some properly positioned text.  Layout and set
  228. ** the menus, then process any events received.  Cleanup when done.
  229. */
  230.  
  231. LONG doWindow()
  232. {
  233. struct Window *window;
  234. struct Screen *screen;
  235. struct DrawInfo *drawinfo;
  236. ULONG  signalmask, signals;
  237. ULONG  win_width, alt_width, win_height;
  238. LONG   returnValue = RETURN_FAIL;
  239. BOOL   done = FALSE;
  240.  
  241. if (screen = LockPubScreen(NULL))
  242.     {
  243.     if (drawinfo = GetScreenDrawInfo(screen))
  244.         {
  245.         /* get the colors for the window text */
  246.         WinText[0].FrontPen = WinText[1].FrontPen = drawinfo->dri_Pens[TEXTPEN];
  247.         WinText[0].BackPen  = WinText[1].BackPen  = drawinfo->dri_Pens[BACKGROUNDPEN];
  248.  
  249.         /* use the screen's font for the text */
  250.         WinText[0].ITextFont = WinText[1].ITextFont = screen->Font;
  251.  
  252.         /* calculate window size */
  253.         win_width  = 100 + IntuiTextLength(&(WinText[0]));
  254.         alt_width  = 100 + IntuiTextLength(&(WinText[1]));
  255.         if (win_width < alt_width)
  256.             win_width  = alt_width;
  257.         win_height = 1 + screen->WBorTop + screen->WBorBottom +
  258.                      (screen->Font->ta_YSize * 5);
  259.  
  260.         /* calculate the correct positions for the text in the window */
  261.         WinText[0].LeftEdge = (win_width - IntuiTextLength(&(WinText[0]))) >> 1;
  262.         WinText[0].TopEdge  = 1 + screen->WBorTop + (2 * screen->Font->ta_YSize);
  263.         WinText[1].LeftEdge = (win_width - IntuiTextLength(&(WinText[1]))) >> 1;
  264.         WinText[1].TopEdge  = WinText[0].TopEdge + screen->Font->ta_YSize;
  265.  
  266.         /* Open the window */
  267.         window = OpenWindowTags(NULL,
  268.             WA_PubScreen, screen,
  269.             WA_IDCMP,     IDCMP_MENUPICK | IDCMP_CLOSEWINDOW | IDCMP_MENUHELP,
  270.             WA_Flags,     WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET |
  271.                               WFLG_ACTIVATE | WFLG_NOCAREREFRESH,
  272.             WA_Left,      10,             WA_Top,       screen->BarHeight + 1,
  273.             WA_Width,     win_width,      WA_Height,    win_height,
  274.             WA_Title,     "Menu Example", WA_MenuHelp,  TRUE,
  275.             TAG_END);
  276.  
  277.  
  278.  
  279.         if (window)
  280.             {
  281.             returnValue = RETURN_OK;  /* program initialized ok */
  282.  
  283.             /* Give a brief explanation of the program */
  284.             PrintIText(window->RPort,&WinText[1],0,0);
  285.  
  286.             /* Adjust the menu to conform to the font (TextAttr) */
  287.             adjustMenus(FirstMenu, window->WScreen->Font);
  288.  
  289.             /* attach the menu to the window */
  290.             SetMenuStrip(window, FirstMenu);
  291.  
  292.             /* Set up the signals that you want to hear about ... */
  293.             signalmask = 1L << window->UserPort->mp_SigBit;
  294.  
  295.             /* And wait to hear from your signals */
  296.             while (!done)
  297.                 {
  298.                 signals = Wait(signalmask);
  299.                 if (signals & signalmask) done = handleIDCMP(window);
  300.                 };
  301.  
  302.             /* clean up everything used here */
  303.             ClearMenuStrip(window);
  304.             CloseWindow(window);
  305.             }
  306.         FreeScreenDrawInfo(screen,drawinfo);
  307.         }
  308.     UnlockPubScreen(NULL,screen);
  309.     }
  310. return(returnValue);
  311. }
  312.  
  313. /* print out what menu was selected.  Properly handle the IDCMP_MENUHELP
  314. ** events.  Set done to TRUE if quit is selected.
  315. */
  316. BOOL processMenus(USHORT selection, BOOL done)
  317. {
  318. USHORT flags;
  319. USHORT menuNum, itemNum, subNum;
  320.  
  321. menuNum = MENUNUM(selection);
  322. itemNum = ITEMNUM(selection);
  323. subNum  = SUBNUM(selection);
  324.  
  325. /* when processing IDCMP_MENUHELP, you are not guaranteed
  326. ** to get a menu item.
  327. */
  328. if (itemNum != NOITEM)
  329.     {
  330.     flags = ((struct MenuItem *)ItemAddress(FirstMenu,(LONG)selection))->Flags;
  331.     if (flags & CHECKED)
  332.         printf("(Checked) ");
  333.     }
  334.  
  335. switch (menuNum)
  336.     {
  337.     case 0:      /* Project Menu */
  338.         switch (itemNum)
  339.             {
  340.             case NOITEM: printf("Project Menu\n");        break;
  341.             case 0:      printf("New\n");                 break;
  342.             case 1:      printf("Open\n");                break;
  343.             case 2:      printf("Save\n");                break;
  344.             case 3:      printf("Save As\n");             break;
  345.             case 4:      printf("Print ");
  346.                 switch (subNum)
  347.                     {
  348.                     case NOSUB: printf("Item\n");  break;
  349.                     case 0:     printf("NLQ\n");   break;
  350.                     case 1:     printf("Draft\n"); break;
  351.                     }
  352.                 break;
  353.             case 5:      printf("About\n");               break;
  354.             case 6:      printf("Quit\n");   done = TRUE; break;
  355.             }
  356.         break;
  357.  
  358.  
  359.  
  360.  
  361.  
  362.     case 1:      /* Edit Menu */
  363.         switch (itemNum) {
  364.             case NOITEM: printf("Edit Menu\n"); break;
  365.             case 0:      printf("Cut\n");       break;
  366.             case 1:      printf("Copy\n");      break;
  367.             case 2:      printf("Paste\n");     break;
  368.             case 3:      printf("Erase\n");     break;
  369.             case 4:      printf("Undo\n");      break;
  370.             }
  371.         break;
  372.     case 2:      /* Settings Menu */
  373.         switch (itemNum) {
  374.             case NOITEM: printf("Settings Menu\n"); break;
  375.             case 0:      printf("Sound\n");            break;
  376.             case 1:      printf("Auto Save\n");        break;
  377.             case 2:      printf("Have Your Cake\n");   break;
  378.             case 3:      printf("Eat It Too\n");       break;
  379.             }
  380.         break;
  381.     case NOMENU: /* No menu selected, can happen with IDCMP_MENUHELP */
  382.         printf("no menu\n");
  383.         break;
  384.     }
  385. return(done);
  386. }
  387.  
  388. /* Handle the IDCMP messages.  Set done to TRUE if quit or closewindow is selected. */
  389. BOOL handleIDCMP(struct Window *win)
  390. {
  391. BOOL done;
  392. USHORT code, selection;
  393. struct IntuiMessage *message = NULL;
  394. ULONG  class;
  395.  
  396. done = FALSE;
  397.  
  398. /* Examine pending messages */
  399. while (message = (struct IntuiMessage *)GetMsg(win->UserPort)) {
  400.     class = message->Class;
  401.     code = message->Code;
  402.  
  403.     /* When we're through with a message, reply */
  404.     ReplyMsg((struct Message *)message);
  405.  
  406.     /* See what events occurred */
  407.     switch (class) {
  408.         case IDCMP_CLOSEWINDOW:
  409.             done = TRUE;
  410.             break;
  411.         case IDCMP_MENUHELP:
  412.             /*
  413.             ** The routine that handles the menus for IDCMP_MENUHELP must be very careful
  414.             ** it can receive menu information that is impossible under IDCMP_MENUPICK.
  415.             ** For instance, the code value on a IDCMP_MENUHELP may have a valid number
  416.             ** for the menu, then NOITEM and NOSUB. IDCMP_MENUPICK would get MENUNULL
  417.             ** in this case.  IDCMP_MENUHELP never come as multi-select items, and the
  418.             ** event terminates the menu processing session.
  419.             **
  420.             ** Note that I do not keep the return value from the processMenus() routine here--the
  421.             ** application should not quit if the user selects "help" over the quit menu item.
  422.             */
  423.             printf("IDCMP_MENUHELP: Help on ");
  424.             processMenus(code,done);
  425.             break;
  426.         case IDCMP_MENUPICK:
  427.             for ( selection = code; selection != MENUNULL;
  428.                   selection = (ItemAddress(FirstMenu,(LONG)selection))->NextSelect)
  429.                 {
  430.                 printf("IDCMP_MENUPICK: Selected ");
  431.                 done = processMenus(selection,done);
  432.                 }
  433.             break;
  434.         }
  435.     }
  436. return(done);
  437. }
  438. /* Steps thru each item to determine the maximum width of the strip */
  439. USHORT MaxLength(struct RastPort *textRPort, struct MenuItem *first_item, USHORT char_size)
  440. {
  441. USHORT maxLength;
  442. USHORT total_textlen;
  443. struct MenuItem  *cur_item;
  444. struct IntuiText *itext;
  445. USHORT extra_width;
  446. USHORT maxCommCharWidth;
  447. USHORT commCharWidth;
  448.  
  449. extra_width = char_size;  /* used as padding for each item. */
  450.  
  451. /* Find the maximum length of a command character, if any.
  452. ** If found, it will be added to the extra_width field.
  453. */
  454. maxCommCharWidth = 0;
  455. for (cur_item = first_item; cur_item != NULL; cur_item = cur_item->NextItem)
  456.     {
  457.     if (cur_item->Flags & COMMSEQ)
  458.         {
  459.         commCharWidth = TextLength(textRPort,&(cur_item->Command),1);
  460.         if (commCharWidth > maxCommCharWidth)
  461.             maxCommCharWidth = commCharWidth;
  462.         }
  463.     }
  464.  
  465. /* if we found a command sequence, add it to the extra required space.  Add
  466. ** space for the Amiga key glyph plus space for the command character.  Note
  467. ** this only works for HIRES screens, for LORES, use LOWCOMMWIDTH.
  468. */
  469. if (maxCommCharWidth > 0)
  470.     extra_width += maxCommCharWidth + COMMWIDTH;
  471.  
  472. /* Find the maximum length of the menu items, given the extra width calculated above. */
  473. maxLength = 0;
  474. for (cur_item = first_item; cur_item != NULL; cur_item = cur_item->NextItem)
  475.     {
  476.     itext = (struct IntuiText *)cur_item->ItemFill;
  477.     total_textlen = extra_width + itext->LeftEdge +
  478.           TextLength(textRPort, itext->IText, strlen(itext->IText));
  479.  
  480.     /* returns the greater of the two */
  481.     if (total_textlen > maxLength)
  482.         maxLength = total_textlen;
  483.     }
  484. return(maxLength);
  485. }
  486.  
  487. /* Set all IntuiText in a chain (they are linked through the NextText ** field) to the same font. */
  488. VOID setITextAttr(struct IntuiText *first_IText, struct TextAttr *textAttr)
  489. {
  490. struct IntuiText *cur_IText;
  491.  
  492. for (cur_IText = first_IText; cur_IText != NULL; cur_IText = cur_IText->NextText)
  493.     cur_IText->ITextFont = textAttr;
  494. }
  495.  
  496.  
  497. /* Adjust the MenuItems and SubItems */
  498. VOID adjustItems(struct RastPort *textRPort, struct MenuItem *first_item,
  499.                  struct TextAttr *textAttr, USHORT char_size, USHORT height,
  500.                  USHORT level, USHORT left_edge)
  501. {
  502. register USHORT item_num;
  503. struct   MenuItem *cur_item;
  504. USHORT   strip_width, subitem_edge;
  505.  
  506. if (first_item == NULL)
  507.     return;
  508.  
  509. /* The width of this strip is the maximum length of its members. */
  510. strip_width = MaxLength(textRPort, first_item, char_size);
  511.  
  512.  
  513.  
  514. /* Position the items. */
  515. for (cur_item = first_item, item_num = 0; cur_item != NULL; cur_item = cur_item->NextItem, item_num++)
  516.     {
  517.     cur_item->TopEdge  = (item_num * height) - level;
  518.     cur_item->LeftEdge = left_edge;
  519.     cur_item->Width    = strip_width;
  520.     cur_item->Height   = height;
  521.  
  522.     /* place the sub_item 3/4 of the way over on the item. */
  523.     subitem_edge = strip_width - (strip_width >> 2);
  524.  
  525.     setITextAttr((struct IntuiText *)cur_item->ItemFill, textAttr);
  526.     adjustItems(textRPort,cur_item->SubItem,textAttr,char_size,height,1,subitem_edge);
  527.     }
  528. }
  529.  
  530.  
  531. /* The following routines adjust an entire menu system to conform to the specified fonts' width and
  532. ** height.  Allows for Proportional Fonts. This is necessary for a clean look regardless of what the
  533. ** users preference in Fonts may be.  Using these routines, you don't need to specify TopEdge,
  534. ** LeftEdge, Width or Height in the MenuItem structures.
  535. **
  536. ** NOTE that this routine does not work for menus with images, but assumes that all menu items are
  537. ** rendered with IntuiText.
  538. **
  539. ** This set of routines does NOT check/correct if the menu runs off
  540. ** the screen due to large fonts, too many items, lo-res screen.
  541. */
  542. BOOL adjustMenus(struct Menu *first_menu, struct TextAttr *textAttr)
  543. {
  544. struct RastPort   textrp = {0};             /* Temporary RastPort */
  545. struct Menu      *cur_menu;
  546. struct TextFont  *font;                     /* Font to use */
  547. USHORT            start, char_size, height;
  548. BOOL              returnValue = FALSE;
  549.  
  550. /* open the font */
  551. if (font = OpenFont(textAttr))
  552.     {
  553.     SetFont(&textrp, font);       /* Put font into temporary RastPort */
  554.  
  555.     char_size = TextLength(&textrp, "n", 1);    /* Get the Width of the Font */
  556.  
  557.     /* To prevent crowding of the Amiga key when using COMMSEQ, don't allow the items to be less
  558.     ** than 8 pixels high.  Also, add an extra pixel for inter-line spacing.
  559.     */
  560.     if (font->tf_YSize > 8)
  561.         height = 1 + font->tf_YSize;
  562.     else
  563.         height = 1 + 8;
  564.  
  565.     start = 2;      /* Set Starting Pixel */
  566.  
  567.     /* Step thru the menu structure and adjust it */
  568.     for (cur_menu = first_menu; cur_menu != NULL; cur_menu = cur_menu->NextMenu)
  569.         {
  570.         cur_menu->LeftEdge = start;
  571.         cur_menu->Width = char_size +
  572.             TextLength(&textrp, cur_menu->MenuName, strlen(cur_menu->MenuName));
  573.         adjustItems(&textrp, cur_menu->FirstItem, textAttr, char_size, height, 0, 0);
  574.         start += cur_menu->Width + char_size + char_size;
  575.         }
  576.     CloseFont(font);              /* Close the Font */
  577.     returnValue = TRUE;
  578.     }
  579. return(returnValue);
  580. }
  581.